package com.mc.fastkit.utils

import android.Manifest
import android.app.ActivityManager
import android.app.ActivityManager.RunningAppProcessInfo
import android.content.Intent
import android.content.pm.PackageManager
import android.graphics.drawable.Drawable
import android.net.Uri
import android.os.Build
import android.os.Environment
import android.os.Process
import androidx.annotation.RequiresApi
import androidx.annotation.RequiresPermission
import androidx.core.content.FileProvider
import com.mc.fastkit.ext.app
import com.mc.fastkit.log.LogUtils
import com.mc.fastkit.widget.ActivityStack
import java.io.File
import kotlin.system.exitProcess

/**
 * AppUtils
 * @author: MasterChan
 * @date: 2022-9-13 23:08
 */
object AppUtils {

    /**
     * 是否适配了分区存储
     */
    val isScopedStorage: Boolean
        get() = Build.VERSION.SDK_INT >= 29 && !Environment.isExternalStorageLegacy()

    /**
     * 是否前台运行
     */
    val isForeground: Boolean
        get() {
            val activityManager = app.getSystemService(ActivityManager::class.java)
            activityManager.runningAppProcesses?.forEach {
                it.pkgList[0]
                if (it.importance == RunningAppProcessInfo.IMPORTANCE_FOREGROUND) {
                    if (it.processName == app.applicationInfo.processName) {
                        return true
                    }
                }
            }
            return false
        }

    /**
     * 获取进程名称
     * @param pid 进程ID
     * @return String?
     */
    fun getProcessName(pid: Int = Process.myPid()): String? {
        val activityManager = app.getSystemService(ActivityManager::class.java)
        activityManager.runningAppProcesses?.forEach {
            if (it.pid == pid) {
                return it.processName
            }
        }
        return null
    }

    /**
     * 判断某个服务是否在运行
     * @param className String
     * @return Boolean
     */
    private fun isServiceRunning(className: String): Boolean {
        val am = app.getSystemService(ActivityManager::class.java)
        val runningServices = am.getRunningServices(Int.MAX_VALUE)
        var isRunning = false
        for (service in runningServices) {
            if (service.service.className == className) {
                isRunning = true
            }
        }
        return isRunning
    }

    /**
     * 安装应用，Target Api大于25需要[Manifest.permission.REQUEST_INSTALL_PACKAGES]权限
     * @param filePath String
     */
    @RequiresPermission(Manifest.permission.REQUEST_INSTALL_PACKAGES)
    fun installApk(filePath: String?) {
        installApk(FileUtils.generateFile(filePath))
    }

    /**
     * 安装应用，Target Api大于25需要[Manifest.permission.REQUEST_INSTALL_PACKAGES]权限
     * @param file File?
     */
    @RequiresPermission(Manifest.permission.REQUEST_INSTALL_PACKAGES)
    fun installApk(file: File?) {
        if (!FileUtils.isExist(file)) {
            return
        }
        val uri = if (Build.VERSION.SDK_INT < Build.VERSION_CODES.N) {
            Uri.fromFile(file)
        } else {
            val authority = "${app.packageName}.fileProvider"
            FileProvider.getUriForFile(app, authority, file!!)
        }
        return installApk(uri)
    }

    /**
     * 安装应用，Target Api大于25需要[Manifest.permission.REQUEST_INSTALL_PACKAGES]权限
     * @param uri Uri?
     */
    @RequiresPermission(Manifest.permission.REQUEST_INSTALL_PACKAGES)
    fun installApk(uri: Uri) {
        val intent = Intent(Intent.ACTION_VIEW)
        intent.setDataAndType(uri, "application/vnd.android.package-archive")
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
            intent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION)
        }
        intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK)
        app.startActivity(intent)
    }

    /**
     * 卸载应用，25以后新增权限，Target Api大于25需要[Manifest.permission.REQUEST_DELETE_PACKAGES]权限
     * @param packageName String
     */
    @RequiresApi(Build.VERSION_CODES.O)
    @RequiresPermission(Manifest.permission.REQUEST_DELETE_PACKAGES)
    fun uninstallApk(packageName: String) {
        val intent = Intent(Intent.ACTION_DELETE)
        intent.data = Uri.parse("package:$packageName")
        intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK)
        app.startActivity(intent)
    }

    /**
     * 应用是否安装
     * @param packageName String
     * @return Boolean
     */
    fun isInstallApk(packageName: String): Boolean {
        return try {
            app.packageManager.getApplicationInfo(packageName, 0).enabled
        } catch (e: Exception) {
            e.printStackTrace()
            false
        }
    }

    /**
     * 启动APP，需要在AndroidManifest中添加<queries>
     * @param packageName String
     */
    fun launchApp(packageName: String) {
        var intent = Intent(Intent.ACTION_MAIN, null)
        intent.addCategory(Intent.CATEGORY_LAUNCHER)
        intent.setPackage(packageName)
        val info = app.packageManager.queryIntentActivities(intent, 0)
        val launcherActivity = info[0].activityInfo.name
        if (launcherActivity.isNullOrEmpty()) {
            LogUtils.d("未找到相应的启动Activity")
            return
        }
        intent = Intent(Intent.ACTION_MAIN)
        intent.addCategory(Intent.CATEGORY_LAUNCHER)
        intent.setClassName(packageName, launcherActivity)
        intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK)
        app.startActivity(intent)
    }

    /**
     * 获取APP图标
     * @param packageName String
     * @return Drawable?
     */
    fun getAppIcon(packageName: String): Drawable? {
        return try {
            val pm = app.packageManager
            pm.getPackageInfo(packageName, 0)?.applicationInfo?.loadIcon(pm)
        } catch (e: PackageManager.NameNotFoundException) {
            e.printStackTrace()
            null
        }
    }

    /**
     * 获取App名称
     * @param packageName String
     * @return String?
     */
    fun getAppName(packageName: String = app.packageName): String? {
        return try {
            val packageInfo = app.packageManager.getPackageInfo(packageName, 0)
            packageInfo?.applicationInfo?.loadLabel(app.packageManager)?.toString()
        } catch (e: Throwable) {
            null
        }
    }

    /**
     * 退出App
     */
    fun exitApp() {
        ActivityStack.instance.finishAll()
        exitProcess(0)
    }
}